package com.leyou.item.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.common.constant.MessageConstant;
import com.leyou.common.domain.PageResult;
import com.leyou.common.enums.ItemExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.dto.BrandDto;
import com.leyou.dto.SkuDTO;
import com.leyou.dto.SpuDetailDTO;
import com.leyou.dto.SpuDto;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.BrandService;
import com.leyou.item.service.CategoryService;
import com.leyou.item.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @version V1.0
 * @author: Ljxpa
 * @date: 2020/03/08 11:43
 * @description:
 */
@Service
@Slf4j
public class GoodsServiceImpl implements GoodsService {

	@Autowired
	private SpuMapper spuMapper;
	@Autowired
	private CategoryService categoryService;
	@Autowired
	private BrandService brandService;
	@Autowired
	private SpuDetailMapper spuDetailMapper;
	@Autowired
	private SkuMapper skuMapper;


	/**
	 * 根据关键字模糊查询，是否上架查询，页数和每页条数查询
	 *
	 * @param key      模糊查询的关键字
	 * @param saleable 是否上架
	 * @param page     当前页数
	 * @param rows     每页条数
	 * @return SpuDto集合
	 */
	@Override
	public PageResult<SpuDto> pageQuerySpu(String key, Boolean saleable, Integer page, Integer rows) {

		Page<Spu> startPage = PageHelper.startPage(page, rows);
		Example example = new Example(Spu.class);
		Example.Criteria criteria = example.createCriteria();
		//如果查询的关键子不为空，则进行关键字模糊查询
		if (StringUtils.isNotBlank(key)) {
			criteria.andLike("name", "%" + key + "%");
		}
		//上架字段不为null，根据上架情况进行查询
		if (null != saleable) {
			criteria.andEqualTo("saleable", saleable);
		}
		//查询所有spu
		List<Spu> spuList = spuMapper.selectByExample(example);
		if (CollectionUtils.isEmpty(spuList)) {
			throw new LyException(ItemExceptionEnum.DATA_NOT_FOUND);
			// return null;
		}

		List<SpuDto> spuDtoList = BeanHelper.copyWithCollection(spuList, SpuDto.class);
		for (SpuDto spuDto : spuDtoList) {
			//根据spu的cid集合查询出对应的所有品类对象集合
			List<Category> categoryListy = categoryService.queryCategoriesByCids(spuDto.getCategoryIds());
			//使用stream流的方式取出每个对象中的name通过/分割，组成以各字符串
			String categorieyNames = categoryListy.stream().map(Category::getName).collect(Collectors.joining("/"));
			spuDto.setCategoryName(categorieyNames);//将种类名称set到每个spuDto中

			//获取该spu的品牌然后set到spuDTO中
			BrandDto brandDto = brandService.queryById(spuDto.getBrandId());
			spuDto.setBrandName(brandDto.getName());
		}
		return new PageResult<SpuDto>(startPage.getTotal(), spuDtoList);
	}

	/**
	 * 添加spu，spudetail，sku
	 * @param spuDto 商品所需所有参数对象
	 */
	@Override
	@Transactional
	public void addGood(SpuDto spuDto) {
		Spu spu = BeanHelper.copyProperties(spuDto, Spu.class);

		spu.setSaleable(true);
		int count = spuMapper.insertSelective(spu);// 区别与insert(Object)方法，insert方法会使用参数对象的所有变量值，如果变量值为null也会存到数据库中，
		// insertSelective方法不会把null值存到数据库中，会使用数据库中指定字段的默认值
		//添加到spu表
		if (1 != count) {
			throw new LyException(ItemExceptionEnum.DATA_SAVE_ERROR);
		}
		SpuDetailDTO spuDetailDto = spuDto.getSpuDetail();
		spuDetailDto.setSpuId(spu.getId());
		//添加到spudetail表
		count = spuDetailMapper.insert(BeanHelper.copyProperties(spuDetailDto, SpuDetail.class));
		if (1 != count) {
			throw new LyException(ItemExceptionEnum.DATA_SAVE_ERROR);
		}

		List<SkuDTO> skuDtoList = spuDto.getSkus();
		List<Sku> skuList = skuDtoList.stream().map(skuDTO -> {
			Sku sku = BeanHelper.copyProperties(skuDTO, Sku.class);
			sku.setSpuId(spu.getId());
			return sku;
		}).collect(Collectors.toList());
		count = skuMapper.insertList(skuList);
		if (count != skuList.size()) {
			throw new LyException(ItemExceptionEnum.DATA_SAVE_ERROR);
		}
	}

	/**
	 * 根据spuId查询对应的spuDetail
	 * @param spuId spuId
	 * @return 对应的spuDetailDto
	 */
	@Override
	public SpuDetailDTO querySpuDetailBySpuId(Long spuId) {
		SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(spuId);

		return BeanHelper.copyProperties(spuDetail, SpuDetailDTO.class);
	}

	/**
	 * 根据spuId查询所有Sku
	 * @param spuId spuId
	 * @return 对应的sku的list集合
	 */
	@Override
	public List<SkuDTO> querySkuBySpuId(Long spuId) {
		Sku sku = new Sku();
		sku.setSpuId(spuId);
		List<Sku> skuList = skuMapper.select(sku);
		return BeanHelper.copyWithCollection(skuList, SkuDTO.class);
	}

	/**
	 * 修改spu,spudetail和所有sku
	 *
	 * @param spuDto spu信息
	 *               TODO spu和sku的修改
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void editGood(SpuDto spuDto) {
		//1，先修改spu和spuDetail表格中的数据
		Spu spu = BeanHelper.copyProperties(spuDto, Spu.class);
		int count = spuMapper.updateByPrimaryKeySelective(spu);
		if (1 != count) {
			throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
		}
		count = spuDetailMapper.updateByPrimaryKeySelective(BeanHelper.copyProperties(spuDto.getSpuDetail(), SpuDetail.class));
		if (1 != count) {
			throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
		}

		//2，修改sku
		List<Sku> skuList = BeanHelper.copyWithCollection(spuDto.getSkus(), Sku.class);
		//2.1，根据spuId查询出原有的所有sku
		Sku record = new Sku();
		record.setSpuId(spuDto.getId());
		List<Sku> oldSkuList = skuMapper.select(record);
		LinkedList<Sku> insertSkuList = new LinkedList<>();

		//2.2，遍历前端传来的skus，
		skuList.forEach(sku -> {
			if (null == sku.getId()) {
				//将传过来的sku中id为null的值添加到待插入的list表中
				sku.setSpuId(spuDto.getId());
				insertSkuList.add(sku);
			} else {
				//传过来的sku的id不为null，与原有sku进行比较，两个集合中都有的表示需要修改，老集合中有的，提交的集合中没有的表示需要删除
				oldSkuList.removeIf(oldSku -> oldSku.getId().longValue() == sku.getId().longValue());
				skuMapper.updateByPrimaryKeySelective(sku);
			}
		});

		//2.3，如果待插入的列表不为空,表示有新添加的sku，则执行添加操作
		if (!CollectionUtils.isEmpty(insertSkuList)) {
			count = skuMapper.insertList(insertSkuList);
			if (count != insertSkuList.size()) {
				throw new LyException(ItemExceptionEnum.DATA_SAVE_ERROR);
			}
		}

		//2.4，老的sku集合经过判断删除之后，剩下的都是需要删除的，判断一下处理之后的旧集合是否还有数据，如果有表示有待删除的
		if (!CollectionUtils.isEmpty(oldSkuList)) {
			List<Long> deleteList = oldSkuList.stream().map(Sku::getId).collect(Collectors.toList());
			count = skuMapper.deleteByIdList(deleteList);
			if (count != oldSkuList.size()) {
				throw new LyException(ItemExceptionEnum.DATA_SAVE_ERROR);
			}
		}
	}


	/**
	 * 处理spu,sku上下架操作
	 *
	 * @param spuId    spuId
	 * @param saleable 是否上架，sku表中使用的是enable字段
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateSaleable(Long spuId, Boolean saleable) {
		//修改spu上下架
		Spu spu = new Spu();
		spu.setSaleable(saleable);
		spu.setId(spuId);
		int count = 0;
		try {
			count = spuMapper.updateByPrimaryKeySelective(spu);

		} catch (Exception e) {
			log.error(MessageConstant.UPDATE_SPU_SALEABLE_ERROR);
			throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
		}
		if (count != 1) {
			throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
		}

		//修改spu对象的sku上下架,spu对应多个sku，修改不支持批量操作，这里使用循环修改
		Example example = new Example(Sku.class);
		example.createCriteria().andEqualTo("spuId", spuId);
		try {
			List<Sku> skus = skuMapper.selectByExample(example);
			for (Sku sku : skus) {
				sku.setEnable(saleable);
				count = skuMapper.updateByPrimaryKey(sku);
				if (1 != count) {
					throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
				}
			}
		} catch (Exception e) {
			log.error(MessageConstant.UPDATE_SKU_SALEABLE_ERROR);
			throw new LyException(ItemExceptionEnum.DATA_UPDATE_ERROR);
		}
	}



}

